use serde::{Deserialize, Serialize};
use std::env;

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Config {
    pub server: ServerConfig,
    pub tms: TmsConfig,
    pub logging: LoggingConfig,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ServerConfig {
    pub name: String,
    pub version: String,
    pub description: String,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TmsConfig {
    pub server_url: String,
    pub connection_timeout_ms: u64,
    pub request_timeout_ms: u64,
    pub max_retries: u32,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct LoggingConfig {
    pub level: String,
    pub format: String,
}

impl Default for Config {
    fn default() -> Self {
        Self {
            server: ServerConfig {
                name: "tms-mcp".to_string(),
                version: "0.1.0".to_string(),
                description: "TMS MCP Server - Model Context Protocol server for Transportation Management System".to_string(),
            },
            tms: TmsConfig {
                server_url: "http://localhost:50051".to_string(),
                connection_timeout_ms: 10000,
                request_timeout_ms: 30000,
                max_retries: 3,
            },
            logging: LoggingConfig {
                level: "info".to_string(),
                format: "json".to_string(),
            },
        }
    }
}

impl Config {
    pub fn from_env() -> Self {
        let mut config = Config::default();
        
        // Override with environment variables
        if let Ok(server_url) = env::var("TMS_SERVER_URL") {
            config.tms.server_url = server_url;
        }
        
        if let Ok(log_level) = env::var("LOG_LEVEL") {
            config.logging.level = log_level;
        }
        
        if let Ok(timeout) = env::var("TMS_CONNECTION_TIMEOUT_MS") {
            if let Ok(timeout_ms) = timeout.parse::<u64>() {
                config.tms.connection_timeout_ms = timeout_ms;
            }
        }
        
        if let Ok(timeout) = env::var("TMS_REQUEST_TIMEOUT_MS") {
            if let Ok(timeout_ms) = timeout.parse::<u64>() {
                config.tms.request_timeout_ms = timeout_ms;
            }
        }
        
        if let Ok(retries) = env::var("TMS_MAX_RETRIES") {
            if let Ok(max_retries) = retries.parse::<u32>() {
                config.tms.max_retries = max_retries;
            }
        }
        
        config
    }
    
    pub fn load_from_file(path: &str) -> anyhow::Result<Self> {
        let content = std::fs::read_to_string(path)?;
        let config: Config = toml::from_str(&content)?;
        Ok(config)
    }
    
    pub fn save_to_file(&self, path: &str) -> anyhow::Result<()> {
        let content = toml::to_string_pretty(self)?;
        std::fs::write(path, content)?;
        Ok(())
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    
    #[test]
    fn test_default_config() {
        let config = Config::default();
        assert_eq!(config.server.name, "tms-mcp");
        assert_eq!(config.tms.server_url, "http://localhost:50051");
        assert_eq!(config.logging.level, "info");
    }
    
    #[test]
    fn test_config_serialization() {
        let config = Config::default();
        let toml_str = toml::to_string(&config).unwrap();
        let deserialized: Config = toml::from_str(&toml_str).unwrap();
        assert_eq!(config.server.name, deserialized.server.name);
    }
}